package com.software.comment.service.impl;

import com.alibaba.excel.util.BooleanUtils;
import com.software.comment.mapper.CommentMapper;
import com.software.comment.pojo.Comment;
import com.software.comment.service.CommentService;
import jakarta.annotation.Resource;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @author 周昊
 * @since 2024/12/16 11：34
 * @version 1.0
 */
@Service
public class CommentServiceImpl implements CommentService {

    /**
     * 用于操作评论数据库
     */
    @Resource
    private CommentMapper commentMapper;

    /**
     * 用于操作redis缓存，此处包含评论置顶状态同步
     */
    @Resource
    private RedisTemplate<String, Integer> redisTemplate;

    @Resource
    private RedisTemplate<String, Comment> commentRedisTemplate;

    /**
     * 添加评论接口实现
     * @param comment 评论对象
     */
    @Override
    public void addComment(Comment comment) {
        comment.setCreateTime(LocalDateTime.now());
        comment.setLevel(1);
        comment.setParentCommentId(0);
        boolean isAdd = commentMapper.addComment(comment);
        if (BooleanUtils.isTrue(isAdd)) {
            String commentRedisKey = "comment:taskId:" + comment.getTaskId() + "commentId" + comment.getId();
            commentRedisTemplate.opsForValue().set(commentRedisKey, comment, 1800, TimeUnit.SECONDS);
        }
    }

    /**
     * 回复评论接口实现
     * @param comment 评论对象
     */
    @Override
    public void replyComment(Comment comment) {
        comment.setCreateTime(LocalDateTime.now());
        comment.setReplyUsername(commentMapper.findCommentsReplyById(comment.getId()));
        if(comment.getLevel() == 1){
            comment.setParentCommentId(comment.getId());
        } else{
            comment.setParentCommentId(comment.getParentCommentId());
        }
        Integer level = comment.getLevel()+1;
        comment.setReplyParentCommentId(comment.getId());
        comment.setLevel(level);
        boolean isAdd = commentMapper.addComment(comment);
        if (BooleanUtils.isTrue(isAdd)) {
            String commentRedisKey = "comment:taskId:" + comment.getTaskId() + "commentId" + comment.getId();
            commentRedisTemplate.opsForValue().set(commentRedisKey, comment, 1800, TimeUnit.SECONDS);
        }
    }

    /**
     * 获取任务下评论列表接口实现
     *
     * @param taskId 任务id
     * @return 评论列表
     * */
    @Override
    public List<Comment> findCommentsByTaskId(Long taskId) {
        return commentMapper.findCommentsByTaskId(taskId);
    }

    /**
     * 删除评论接口实现
     * @param id 任务id
     * @return 评论删除成功
     * */
    @Override
    public boolean deleteCommentById(Long id) {
        commentMapper.deleteCommentByParentId(id);
        return true;
    }

    /**
     * 通过任务id和父评论id获取评论列表接口实现
     * @param taskId 任务id
     * @param parentCommentId 父评论id
     * @return 评论列表
     * */
    @Override
    public List<Comment> findCommentsByTaskIdAndParentId(Long taskId, Long parentCommentId) {
        return commentMapper.findCommentsByTaskIdAndParentId(taskId, parentCommentId);
    }

    /**
     * 评论置顶状态接口实现
     * @param commentId 评论id
     *                    1：置顶
     *                    0：未置顶
     * @return 评论置顶状态
     */
    @Override
    public Integer getIsTopComment(Long commentId) {
        String redisKey = "comment:isTop:" + commentId;
        Integer isTopComment = redisTemplate.opsForValue().get(redisKey);
        if (isTopComment == null) {
            isTopComment = commentMapper.findIsTopComment(commentId);
            if (isTopComment!= null) {
                redisTemplate.opsForValue().set(redisKey, isTopComment, 3600, TimeUnit.SECONDS);
            }
        }
        return isTopComment;
    }

    /**
     * 置顶评论接口实现
     * @param commentId 评论Id 
     */
    @Override
    public void toTopComment(Long commentId) {
        String redisKey = "comment:isTop:" + commentId;
        redisTemplate.opsForValue().set(redisKey, 1, 3600, TimeUnit.SECONDS);
    }

    /**
     * 取消置顶评论接口实现
     * @param commentId 评论Id 
     */
    @Override
    public void cancelTopComment(Long commentId) {
        String redisKey = "comment:isTop:" + commentId;
        redisTemplate.opsForValue().set(redisKey, 0, 3600, TimeUnit.SECONDS);
        System.out.println(redisTemplate.opsForValue().get(redisKey));
    }

    /**
     * 定时任务，每隔30分钟同步一次评论置顶状态到数据库
     */
    @Scheduled(fixedRate = 60*1000*30)
    public void syncIsTopCommentToDatabase() {
        Set<String> redisKeys = redisTemplate.keys("comment:isTop:*");
        if (redisKeys!= null &&!redisKeys.isEmpty()) {
            for (String redisKey : redisKeys) {
                Long commentId = Long.parseLong(redisKey.split(":")[2]);
                Integer isTopComment = redisTemplate.opsForValue().get(redisKey);
                if (isTopComment!= null) {
                    commentMapper.updateIsTopCommentInDataBase(commentId, isTopComment);
                }
            }
        }
    }

    /**
     * 查找评论评论的上下层级相关列表接口实现
     * @param commentId 评论Id
     * @return 评论评论的上下层级相关评论列表
     * */
    @Override
    public List<Comment> findAllRelatedCommentsById(Integer commentId) {
        List<Comment> relatedComments = new ArrayList<>();
        Comment currentComment = commentMapper.getCommentById(commentId);
        if (currentComment!= null) {
            // 向上查找关联评论
            findParentComments(commentId, relatedComments);
            relatedComments.add(currentComment);
            // 向下查找关联评论
            findChildComments(commentId, relatedComments);
        }
        return relatedComments;
    }

    /**
     * 查找评论评论的上层级相关列表接口实现
     * @param commentId 评论Id
     * @param relatedComments 评论评论的上层级相关评论列表
     */
    private void findParentComments(Integer commentId, List<Comment> relatedComments) {
        Integer parentCommentId = commentMapper.getCommentById(commentId).getReplyParentCommentId();
        while (parentCommentId != null) {
            Comment parentComment = commentMapper.getParentCommentByReplyParentCommentId(parentCommentId);
            if (parentComment != null) {
                relatedComments.add(parentComment);
                parentCommentId = parentComment.getReplyParentCommentId();
            } else {
                break;
            }
        }
        // 排序
        relatedComments.sort(Comparator.comparing(Comment::getId));
    }

    /**
     * 查找评论评论的下层级相关列表接口实现
     * @param commentId 评论Id
     * @param relatedComments 评论评论的上层级相关评论列表
     */
    private void findChildComments(Integer commentId, List<Comment> relatedComments) {
        List<Comment> childComments = commentMapper.getChildCommentsByCommentId(commentId);
        if (childComments!= null &&!childComments.isEmpty()) {
            relatedComments.addAll(childComments);
            for (Comment childComment : childComments) {
                findChildComments(childComment.getId(), relatedComments);
            }
        }
    }

}